<template>
  <div>
    <el-form ref="apiTestForm" :model="apiTestForm" label-width="0" action="http://" target="stop">
      <!-- <el-page-header @back="goBack" content="API测试">
    </el-page-header> -->
      <div style="margin-top: 30px">
        <div>
          <el-row :gutter="20" style="margin-top: 20px">
            <el-col :span="20">
              <div>
                <div class="main-font-box">Request</div>
              </div>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="4">
              <div style="text-align: left; color: #c0c4cc; font-size: 0.715em">
                METHOD
              </div>
            </el-col>
            <el-col :span="13">
              <div style="text-align: left; color: #c0c4cc; font-size: 0.715em">
                SCHEME :// HOST [ ":" PORT ] [ PATH [ "?" QUERY ]]
              </div>
            </el-col>
            <el-col :span="3"></el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="4">
              <div>
                <el-form-item label-width="0">
                  <el-select
                    v-model="apiTestForm.httpMethod"
                    placeholder="请选择"
                    @change="httpMethodChange"
                    size="medium"
                    style="width: 100%"
                    :disabled="disable"
                  >
                    <el-option
                      v-for="item in httpMethodOptions"
                      :key="item"
                      :label="item"
                      :value="item"
                    >
                    </el-option>
                  </el-select>
                </el-form-item>
              </div>
            </el-col>
            <el-col :span="13">
              <div>
                <el-form-item
                  prop="url"
                  label-width="0"
                  :rules="[{ required: true, message: '请求地址必填' }]"
                >
                  <el-input
                    size="medium"
                    v-model="apiTestForm.url"
                    placeholder="输入请求地址"
                    name="url"
                    autocomplete="on"
                    :disabled="disable"
                  >
                    <i v-if="apiTestForm.url != null && apiTestForm.url.indexOf('https') != -1" slot="prefix" class="el-icon-lock"></i>
                  </el-input>
                </el-form-item>
              </div>
            </el-col>
            <el-col :span="3">
              <div>
                <el-form-item label-width="0">
                  <el-button
                    v-if="!alreadySend"
                    size="medium"
                    type="primary"
                    icon="el-icon-s-promotion"
                    style="width: 100%"
                    @click="send"
                    >Send</el-button
                  >
                  <el-button
                    v-if="alreadySend"
                    size="medium"
                    type="warning"
                    icon="el-icon-switch-button"
                    style="width: 100%"
                    @click="cancel"
                    >Abort</el-button
                  >
                </el-form-item>
              </div>
            </el-col>
          </el-row>
        </div>
        <el-row :gutter="20" style="margin-top: 10px">
          <el-col :span="8">
            <div style="text-align: left">
              <div style="margin-bottom: 14px">
                <span style="color: #909399">HEADERS</span>
              </div>
              <edit-form
                v-model="apiTestForm.headers"
                addButtonName="添加Headers"
              ></edit-form>
            </div>
          </el-col>
          <el-col :span="12">
            <div style="margin-bottom: 4px">
              <el-row>
                <el-col :span="20" style="text-align: left">
                  <div style="text-align: left; color: #909399">BODY</div>
                </el-col>
                <el-col :span="4" style="text-align: right">
                  <div style="text-align: right;">
                    <el-select
                      v-if="
                        apiTestForm.httpMethod == 'PUT' ||
                        apiTestForm.httpMethod == 'POST'
                      "
                      v-model="bodyType"
                      @change="bodyTypeChange"
                      placeholder=""
                      size="mini"
                    >
                      <el-option
                        v-for="item in bodyTypeOptions"
                        :key="item"
                        :label="item"
                        :value="item"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </el-col>
              </el-row>
            </div>
            <div>
              <div
                v-if="
                  apiTestForm.httpMethod == 'PUT' ||
                  apiTestForm.httpMethod == 'POST'
                "
              >
                <div v-if="bodyType == 'Text'">
                  <el-input
                    id="stringBodyInput"
                    size="medium"
                    type="textarea"
                    v-model="apiTestForm.stringBody"
                    :autosize="{ minRows: 10, maxRows: 20 }"
                    @keydown.9.native.prevent="tabFunc"
                  ></el-input>
                  <div style="text-align: left; margin-top: 2px">
                    <el-radio-group
                      v-model="stringBodyType"
                      size="mini"
                      @change="stringBodyTypeChange"
                    >
                      <el-radio-button
                        v-for="item in stringBodyTypes"
                        :key="item"
                        :label="item"
                      ></el-radio-button>
                    </el-radio-group>
                  </div>
                </div>
                <edit-form
                  v-if="bodyType == 'Form'"
                  addButtonName="添加表单参数"
                  style="text-align: left"
                  v-model="apiTestForm.formData"
                ></edit-form>
              </div>
              <div
                v-if="apiTestForm.httpMethod == null"
                style="margin-top: 18px; text-align: left; color: #c0c4cc"
              >
                Please select http method.
              </div>
              <div
                v-if="
                  apiTestForm.httpMethod == 'GET' ||
                  apiTestForm.httpMethod == 'DELETE'
                "
                style="margin-top: 18px; text-align: left; color: #c0c4cc"
              >
                XHR does not allow payloads for
                <span style="color:#409EFF">{{ apiTestForm.httpMethod }}</span> request.
              </div>
            </div>
          </el-col>
        </el-row>
        <el-row :gutter="20" style="margin-top: 20px">
          <el-col :span="20">
            <div>
              <el-row>
                <el-col :span="12" style="text-align: left">
                  <div class="main-font-box">Response</div>
                </el-col>
                <el-col :span="12" style="text-align: right">
                  <div style="text-align: right; color: #c0c4cc">
                    Elapsed Time: {{ elapsedTime }}ms
                  </div>
                </el-col>
              </el-row>
              <!-- <el-divider content-position="left"><span style="color: #C0C4CC; font-size: 18px;">Response</span></el-divider> -->
              <div style="margin-bottom: 5px">
                <!-- <el-alert style="border-radius: 0;" title="200 OK" type="success" show-icon></el-alert> -->
                <resp-box
                  :status="apiTestResult.status"
                  :msg="apiTestResult.msg"
                ></resp-box>
              </div>
            </div>
          </el-col>
        </el-row>
        <el-row :gutter="20" style="margin-top: 20px">
          <el-col :span="8">
            <div style="text-align: left">
              <div style="margin-bottom: 10px">
                <span style="color: #909399">HEADERS</span>
              </div>
              <div>
                <el-row
                  v-for="item in apiTestResult.headers"
                  :key="item.name"
                  style="margin-bottom: 5px"
                >
                  <el-col :span="10" style="font-size: 14px; color: #c0c4cc">
                    {{ item.name }}:
                  </el-col>
                  <el-col :span="14" style="font-size: 14px; color: #c0c4cc">
                    {{ item.value }}
                  </el-col>
                </el-row>
                <el-empty
                  v-if="
                    apiTestResult.headers == null ||
                    apiTestResult.headers.length == 0
                  "
                  description="Nothing in here"
                ></el-empty>
              </div>
            </div>
          </el-col>
          <el-col :span="12">
            <div style="margin-bottom: 4px">
              <el-row>
                <el-col :span="20" style="text-align: left">
                  <div style="text-align: left; color: #909399">BODY</div>
                </el-col>
                <el-col :span="4" style="text-align: right">
                  <div style="text-align: right;">
                    <el-select
                      v-model="formatType"
                      @change="formatTypeChange"
                      placeholder=""
                      size="mini"
                    >
                      <el-option
                        v-for="item in formatTypeOptions"
                        :key="item"
                        :label="item"
                        :value="item"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </el-col>
              </el-row>
            </div>
            <div>
              <json-viewer v-if="formatType == 'pretty' && apiTestResult.stringBodyForJson" style="text-align: left" :value="apiTestResult.stringBodyForJson" :expand-depth="4" sort></json-viewer>
              <el-input
                v-else
                size="medium"
                type="textarea"
                v-model="apiTestResult.stringBody"
                :autosize="{ minRows: 12, maxRows: 30 }"
              ></el-input>
              <!-- <div v-html="apiTestResult.stringBody" style=""></div> -->
              <div style="text-align: left; margin-top: 2px">
                <el-button-group>
                  <!-- <el-button size="mini" @click="formatStringBody"
                    >Format</el-button
                  > -->
                  <el-button size="mini" @click="copyStringBody"
                    >Copy</el-button
                  >
                </el-button-group>
              </div>
            </div>
          </el-col>
        </el-row>
      </div>
    </el-form>
    <!-- 使用其阻止表单提交 -->
    <iframe name="stop" style="display:none"></iframe>
    <el-backtop></el-backtop>
  </div>
</template>
<script>
import ajax from "~/api/ajax";
import JsonViewer from 'vue-json-viewer'
import respBox from "~/components/respBox";
import editForm from "~/components/editForm";
export default {
  components: {
    "resp-box": respBox,
    "edit-form": editForm,
    "json-viewer": JsonViewer
  },
  data() {
    return {
      apiTestUrl: 'http://localhost:8088',
      disable: false,
      alreadySend: false,
      httpMethodOptions: ["GET", "POST", "DELETE", "PUT"],
      bodyTypeOptions: ["Text", "Form"],
      bodyType: "Text",
      stringBodyType: "Json",
      stringBodyTypes: ["Text", "Json", "XML", "HTML"],
      formatType: 'pretty',
      formatTypeOptions: ['pretty', 'row'],
      apiTestForm: {
        httpMethod: 'GET',
        url: "http://",
        headers: [],
        formData: [],
        stringBody: null,
      },
      apiTestResult: {
        status: 0,
        msg: 'Wait Send.',
        headers: [],
        contentType: null,
        stringBody: null,
        stringBodyForJson: null,
      },
      elapsedTime: 0,
    };
  },

  mounted() {
    var that = this;
    let id = that.$route.query.id;
    if (id != undefined && id != null && id != "") {
      that.disable = true;
      ajax.get("/apiManage/getFormApiConfig/" + id).then((rs) => {
        if (rs.success && rs.data != null) {
          that.apiTestForm.httpMethod = rs.data.httpMethod;
          that.apiTestForm.url = that.apiTestUrl + rs.data.path;
        } else {
          this.$message.error(rs.msg + " 请尝试刷新！");
        }
      });
    }
    this.addContentType();
  },

  methods: {
    goBack() {
      this.$router.go(-1);
    },

    getContentType() {
      let headerValue = null;
      if (this.bodyType == "Form") {
        return "application/x-www-form-urlencoded";
      }
      if (this.stringBodyType == "Text") {
        headerValue = "text/plain";
      } else if (this.stringBodyType == "Json") {
        headerValue = "application/json";
      } else if (this.stringBodyType == "XML") {
        headerValue = "application/xml";
      } else if (this.stringBodyType == "HTML") {
        headerValue = "text/html";
      }

      return headerValue;
    },

    addContentType() {
      let headers = this.apiTestForm.headers;
      let headerValue = this.getContentType();
      if (headers.length == 0) {
        headers.push({
          enable: true,
          name: "Content-Type",
          value: headerValue,
        });
      } else {
        var [...arr] = headers;
        var exist = false;
        for (var i = 0; i < arr.length; i++) {
          if (arr[i].name == "Content-Type") {
            headers.splice(i, 1);
            headers.push({
              enable: true,
              name: "Content-Type",
              value: headerValue,
            });
            exist = true;
            break;
          }
        }
        if (!exist) {
          headers.push({
            enable: true,
            name: "Content-Type",
            value: headerValue,
          });
        }
      }
    },

    httpMethodChange(val) {
      if (val == "POST" || val == "PUT") {
        this.addContentType();
      }
    },

    bodyTypeChange(val) {
      this.addContentType();
    },

    stringBodyTypeChange(val) {
      this.addContentType();
    },

    send() {
      this.$refs['apiTestForm'].$el.submit();
      this.$refs['apiTestForm'].validate((valid) => {
          if (valid) {
            this.beginTimer();
            this.apiTestResult = {status: 0, msg: 'Sending...'};
            this.alreadySend = true;
            ajax.post("/apiManage/testApi", this.apiTestForm).then((rs) => {
              if (rs.success) {
                this.apiTestResult = rs.data;
                if (this.apiTestResult.contentType != null && this.apiTestResult.contentType.toLocaleLowerCase().indexOf("application/json") != -1) {
                  this.apiTestResult.stringBodyForJson = JSON.parse(this.apiTestResult.stringBody);
                }
              } else {
                this.$message.error("请求失败！请稍后再试！");
                this.apiTestResult = {status: -1, msg: 'Error.'};
              }
              this.endTimer();
              this.alreadySend = false;
            })
            .catch((error) => {
              this.$message.error("请求异常或超时！请稍后再试！");
              this.endTimer();
              this.alreadySend = false;
              this.apiTestResult = {status: -1, msg: 'Error.'};
            });
          } else {
            return false;
          }
        });
    },
    tabFunc () {
      this.insertInputTxt('stringBodyInput', '  ');
    },

    insertInputTxt(id, insertTxt) {
      var elInput = document.getElementById(id);
      var startPos = elInput.selectionStart;
      var endPos = elInput.selectionEnd;
      if (startPos === undefined || endPos === undefined) return
      var txt = elInput.value;
      var result = txt.substring(0, startPos) + insertTxt + txt.substring(endPos)
      elInput.value = result;
      elInput.focus();
      elInput.selectionStart = startPos + insertTxt.length;
      elInput.selectionEnd = startPos + insertTxt.length;
    },

    cancel() {

    },

    beginTimer() {
      this.elapsedTime = 0;
      this.timer = setInterval(() => {
        this.elapsedTime++;
      }, 1);
    },

    endTimer() {
      clearInterval(this.timer);
    },

    formatTypeChange(val) {
      // if (val == 'pretty') {
      //   this.formatStringBody();
      // }
    },

    formatStringBody() {
      let stringBody = this.apiTestResult.stringBody;
      if (stringBody == null || stringBody == "") {
        console.log("内容为空！无法格式化！");
        return;
      }
      let contentType = this.apiTestResult.contentType;
      if (contentType == null || contentType == "") {
        this.$message({
          message: "未知的响应内容，无法格式化！",
          type: "warning",
        });
        return;
      }
      if (contentType.toLocaleLowerCase().indexOf("application/json") != -1) {
        let jsonObj = JSON.parse(stringBody);
        this.apiTestResult.stringBody = JSON.stringify(jsonObj, null, "\t");
      } else if (
        contentType.toLocaleLowerCase().indexOf("application/xml") != -1
      ) {
        this.$message({
          message: "暂未实现对xml的格式化！",
          type: "warning",
        });
      } else {
        console.log("contentType:" + contentType + ", 无法格式化！");
      }
    },

    copyStringBody() {
      let stringBody = this.apiTestResult.stringBody;
      if (stringBody == null || stringBody == '') {
        this.$message('No content for copy');
        return;
      }
      var that = this;
      this.$copyText(stringBody).then(
        function (e) {
          that.$message({
            message: 'Copied',
            type: 'success'
          });
        },
        function (e) {
          that.$message.error('Failed to copy');
        }
      );
    },
  },
};
</script>
<style>
.main-font-box {
  text-align: left;
  margin-bottom: 10px;
  font-size: 20px;
  font-weight: bold;
  color: #606266;
}
</style>